import React, {Component} from "react";

interface ScalingProps {
  url?: string;
}

interface ScalingState {
  translates: { x: number; y: number };
  scale: number;
  id: string;
}

export default class Scaling extends Component<ScalingProps, ScalingState> {

  constructor(props: ScalingProps) {
    super(props);
    this.state = {
      translates: {x: 0, y: 0},
      scale: 1,
      id: Math.random().toString(36).substring(2)
    };
  }

  componentDidMount() {
    this.addMonitor();
  }

  addMonitor = () => {
    const {id} = this.state;
    let scalingImg = document.getElementById(`scalingImg${id}`) as HTMLElement;
    let scaling = document.getElementById(`scaling${id}`) as HTMLElement;

    const that = this;

    const util = () => {
      this.removeEvent(scalingImg, "mousewheel", onMouseWheel); //防止多次监听
      this.addEvent(scalingImg, "mousewheel", onMouseWheel);
    };

    this.addEvent(scalingImg, "mouseover", util);
    this.addEvent(scalingImg, "mousedown", this.mousedown);

    this.addEvent(scaling, "mousewheel", function (ev: any) {
      ev.preventDefault(); // 阻止默认事件
      ev.stopPropagation();
    });

    function onMouseWheel(ev: any) {
      const width = scalingImg.clientWidth;
      const height = scalingImg.clientHeight;
      scalingImg.style.transformOrigin = `${width / 2}px ${height / 2}px`;
      let scal = that.state.scale;

      ev.preventDefault(); // 阻止默认事件
      ev.stopPropagation();
      /*当鼠标滚轮事件发生时，执行一些操作*/
      var ev = ev || window.event;
      // let originX = ev.offsetX;
      // let originY = ev.offsetY;

      // 定义一个标志，当滚轮向下滚时，执行一些操作
      var down = ev.wheelDelta ? ev.wheelDelta < 0 : ev.detail > 0;
      if (down) {
        //@ts-ignore
        scal = (parseFloat(scal) + 0.05).toFixed(2);
        // console.log("放大系数: " + scal);
        scalingImg.style.transform = `translate(${that.state.translates.x}px, ${that.state.translates.y}px) scale(${scal})`;
        // scalingImg.style.transformOrigin = `${originX}px ${originY}px`;
        that.setState({
          scale: scal
        });
      } else {
        if (scal < 0.7) {
          scal = 0.7;
          return;
        } else {
          //@ts-ignore
          scal = (parseFloat(scal) - 0.1).toFixed(2);
        }

        let {x, y} = that.state.translates;
        scalingImg.style.transform = `translate(${x}px, ${y}px) scale(${scal})`;
        // scalingImg.style.transformOrigin = `${originX*.5}px ${originY*.5}px`;
        that.setState({
          scale: scal
        });
      }
      return false;
    }
  };

  mousedown = (ev: any) => {
    ev.stopPropagation();
    const that = this;
    const {id} = this.state;
    let scalingImg = document.getElementById(`scalingImg${id}`) as HTMLElement;
    let scaling = document.getElementById(`scaling${id}`) as HTMLElement;

    // console.log("鼠标按下");
    ev.preventDefault();
    let moveStartX = ev.x || ev.clientX;
    let moveStartY = ev.y || ev.clientY;
    let lastTranslateX = this.state.translates.x;
    let lastTranslateY = this.state.translates.y;
    this.addEvent(scaling, "mousemove", mousemove);
    this.addEvent(scaling, "mouseup", removeEvent);
    this.addEvent(scaling, "mouseout", removeEvent);

    /**拖动 */
    function mousemove(ev: any) {
      var x = (ev.x || ev.clientX) - moveStartX + lastTranslateX;
      var y = (ev.y || ev.clientY) - moveStartY + lastTranslateY;
      scalingImg.style.transform = `translate(${x}px, ${y}px) scale(${that.state.scale})`;

      that.setState({
        translates: {x, y}
      });
    }

    /**取消监听 */
    function removeEvent(ev: any) {
      ev.stopPropagation();
      // console.log("鼠标提起或移出");
      that.removeEvent(scaling, "mousemove", mousemove);
      that.removeEvent(scaling, "mouseup", removeEvent);
      that.removeEvent(scaling, "mouseout", removeEvent);
    }
  };

  addEvent(obj: any, xEvent: any, fn: any) {
    if (obj.attachEvent) {
      obj.attachEvent("on" + xEvent, fn);
    } else {
      obj.addEventListener(xEvent, fn, false);
    }
  }

  removeEvent(obj: any, xEvent: any, fn: any) {
    if (obj.detachEvent) {
      obj.detachEvent("on" + xEvent, fn);
    } else {
      obj.removeEventListener(xEvent, fn, false);
    }
  }

  /**重置 */
  reset() {
    const {id} = this.state;
    let scalingImg = document.getElementById(`scalingImg${id}`) as HTMLElement;
    this.setState({translates: {x: 0, y: 0}, scale: 1});
    scalingImg.style.transform = `translate(${0}px, ${0}px) scale(${1})`;
    scalingImg.style.transformOrigin = `${0}px ${0}px`;
  }

  render() {
    const {url} = this.props;
    const {id} = this.state;
    return (
      <span className="scaling" id={`scaling${id}`}>
        <img alt="" src={url} id={`scalingImg${id}`}/>
      </span>
    )
  }
}
